package eureka.consumer.redissonlock;

import eureka.consumer.redissonlock.interfaces.DistributedLockTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.redisson.config.TransportMode;
import org.springframework.beans.factory.FactoryBean;

import javax.annotation.PreDestroy;

/**
 * @Author RenPu
 * @Date 2021/8/26 11:56
 * @Version 1.0
 * @Description:
 **/

@Slf4j
public class RedissonFactoryBean implements FactoryBean<DistributedLockTemplate> {
    private RedissonFactoryBean.LockInstanceMode mode;

    private DistributedLockTemplate distributedLockTemplate;

    private final RedissonClient redisson;

    public RedissonFactoryBean(BaseRedisProperty redissonProperty) {
        log.info("init RedissonFactoryBean redisson: {}", redissonProperty.toString());
        String ip = redissonProperty.getHost();
        Integer port = redissonProperty.getPort();

        BaseRedisProperty.Redisson redisson = redissonProperty.getRedisson();
        Config config = new Config();
        if (TransportMode.EPOLL.name().equalsIgnoreCase(redisson.getTransportMode())) {
            config.setTransportMode(TransportMode.EPOLL);
        }
        SingleServerConfig singleServer = config.useSingleServer();
        singleServer.setAddress("redis://" + ip + ":" + port);
        singleServer.setTimeout(redisson.getTimeOut());
        singleServer.setConnectionPoolSize(redisson.getPoolSize());
        // redis密码校验
        if (StringUtils.isNotEmpty(redissonProperty.getPassword())) {
            singleServer.setPassword(redissonProperty.getPassword());
        }
        singleServer.setConnectionMinimumIdleSize(redisson.getMinIdleSize());
        singleServer.setPingConnectionInterval(1000);
        this.redisson = Redisson.create(config);
        setMode(redisson.getMode());
    }

    @PreDestroy
    public void destroy() {
        log.info("销毁Redisson分布式锁模板");
        redisson.shutdown();
    }

    @Override
    public DistributedLockTemplate getObject() throws Exception {
        switch (mode) {
            case SINGLE:
                distributedLockTemplate = new SingleDistributedLockTemplate(redisson);
                break;
        }
        return distributedLockTemplate;
    }

    @Override
    public Class<?> getObjectType() {
        return DistributedLockTemplate.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    private void setMode(String mode) {
        if (mode == null || mode.length() <= 0 || mode.equals("")) {
            throw new IllegalArgumentException("未找到redisson.mode配置项");
        }
        this.mode = RedissonFactoryBean.LockInstanceMode.parse(mode);
        if (this.mode == null) {
            throw new IllegalArgumentException("不支持的分布式锁模式");
        }
    }

    private enum LockInstanceMode {
        SINGLE;

        public static RedissonFactoryBean.LockInstanceMode parse(String name) {
            for (RedissonFactoryBean.LockInstanceMode modeIns : RedissonFactoryBean.LockInstanceMode.values()) {
                if (modeIns.name().equals(name.toUpperCase())) {
                    return modeIns;
                }
            }
            return null;
        }
    }


}
